package panda.natalia.gothread.suspend.instrument.codesample;

/**
 * a simple framework of java fiber
 *
 * @Author: scpanda2007
 * @Date: 2019/12/3 11:07
 *
 * // class version 52.0 (52)
 * // access flags 0x21
 * public class panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess {
 *
 *   // compiled from: TestSyntheticAccess.java
 *   // access flags 0x0
 *   INNERCLASS panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess$InnerClass panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess InnerClass
 *
 *   // access flags 0x2
 *   private I inner
 *
 *   // access flags 0x1
 *   public <init>()V
 *    L0
 *     LINENUMBER 185 L0
 *     ALOAD 0
 *     INVOKESPECIAL java/lang/Object.<init> ()V
 *    L1
 *     LINENUMBER 186 L1
 *     ALOAD 0
 *     ICONST_0
 *     PUTFIELD panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess.inner : I
 *     RETURN
 *    L2
 *     LOCALVARIABLE this Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess; L0 L2 0
 *     MAXSTACK = 2
 *     MAXLOCALS = 1
 *
 *   // access flags 0x2
 *   private innerMethod()I throws java/lang/Exception
 *    L0
 *     LINENUMBER 187 L0
 *     ICONST_1
 *     IRETURN
 *    L1
 *     LOCALVARIABLE this Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess; L0 L1 0
 *     MAXSTACK = 1
 *     MAXLOCALS = 1
 *
 *   // access flags 0x1008
 *   static synthetic access$000(Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;)I
 *    L0
 *     LINENUMBER 185 L0
 *     ALOAD 0
 *     GETFIELD panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess.inner : I
 *     IRETURN
 *    L1
 *     LOCALVARIABLE x0 Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess; L0 L1 0
 *     MAXSTACK = 1
 *     MAXLOCALS = 1
 *
 *   // access flags 0x1008
 *   static synthetic access$100(Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;)I throws java/lang/Exception
 *    L0
 *     LINENUMBER 185 L0
 *     ALOAD 0
 *     INVOKESPECIAL panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess.innerMethod ()I
 *     IRETURN
 *    L1
 *     LOCALVARIABLE x0 Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess; L0 L1 0
 *     MAXSTACK = 1
 *     MAXLOCALS = 1
 * }
 *
 *  这里可以看到一个 方法 access$000 和 access$100, 另外注意到 私有方法的调用 是 INVOKESPECIAL
 *  注意 acess方法是static的 并且会自动做一些功能, 例如抛出原函数的异常
 *
 *  byteviewer看不到子类 用 javap 打印了一下
 *
 * 由上可以看出具体的构造函数虚拟机实际自动追加了一个外部类实例变量传入的参数 即指向外部类的this变量
 *
 * Classfile /G:/HOME_Panda/gothread/target/classes/panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess$InnerClass.class
 *   Last modified 2019-12-3; size 1101 bytes
 *   MD5 checksum 476763f98c2a8c87384e60e5bb99c122
 *   Compiled from "TestSyntheticAccess.java"
 * class panda.natalia.gothread.suspend.instrument.codesample.TestSyntheticAccess$InnerClass
 *   minor version: 0
 *   major version: 52
 *   flags: ACC_SUPER
 * Constant pool:
 *    #1 = Fieldref           #6.#29         // panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess$InnerClass.this$0:Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;
 *    #2 = Methodref          #7.#30         // java/lang/Object."<init>":()V
 *    #3 = Fieldref           #6.#31         // panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess$InnerClass.any:Ljava/lang/String;
 *    #4 = Methodref          #32.#33        // panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess.access$000:(Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;)I
 *    #5 = Methodref          #32.#34        // panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess.access$100:(Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;)I
 *    #6 = Class              #35            // panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess$InnerClass
 *    #7 = Class              #36            // java/lang/Object
 *    #8 = Utf8               any
 *    #9 = Utf8               Ljava/lang/String;
 *   #10 = Utf8               this$0
 *   #11 = Utf8               Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;
 *   #12 = Utf8               <init>
 *   #13 = Utf8               (Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;Ljava/lang/String;)V
 *   #14 = Utf8               Code
 *   #15 = Utf8               LineNumberTable
 *   #16 = Utf8               LocalVariableTable
 *   #17 = Utf8               this
 *   #18 = Utf8               InnerClass
 *   #19 = Utf8               InnerClasses
 *   #20 = Utf8               Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess$InnerClass;
 *   #21 = Utf8               println
 *   #22 = Utf8               ()V
 *   #23 = Utf8               a
 *   #24 = Utf8               I
 *   #25 = Utf8               Exceptions
 *   #26 = Class              #37            // java/lang/Exception
 *   #27 = Utf8               SourceFile
 *   #28 = Utf8               TestSyntheticAccess.java
 *   #29 = NameAndType        #10:#11        // this$0:Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;
 *   #30 = NameAndType        #12:#22        // "<init>":()V
 *   #31 = NameAndType        #8:#9          // any:Ljava/lang/String;
 *   #32 = Class              #38            // panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess
 *   #33 = NameAndType        #39:#40        // access$000:(Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;)I
 *   #34 = NameAndType        #41:#40        // access$100:(Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;)I
 *   #35 = Utf8               panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess$InnerClass
 *   #36 = Utf8               java/lang/Object
 *   #37 = Utf8               java/lang/Exception
 *   #38 = Utf8               panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess
 *   #39 = Utf8               access$000
 *   #40 = Utf8               (Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;)I
 *   #41 = Utf8               access$100
 * {
 *   final panda.natalia.gothread.suspend.instrument.codesample.TestSyntheticAccess this$0;
 *     descriptor: Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;
 *     flags: ACC_FINAL, ACC_SYNTHETIC
 *
 *   public panda.natalia.gothread.suspend.instrument.codesample.TestSyntheticAccess$InnerClass(panda.natalia.gothread.suspend.instrument.codesample.TestSyntheticAccess, java.lang.String);
 *     descriptor: (Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;Ljava/lang/String;)V
 *     flags: ACC_PUBLIC
 *     Code:
 *       stack=2, locals=3, args_size=3
 *          0: aload_0
 *          1: aload_1
 *          2: putfield      #1                  // Field this$0:Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;
 *          5: aload_0
 *          6: invokespecial #2                  // Method java/lang/Object."<init>":()V
 *          9: aload_0
 *         10: aconst_null
 *         11: putfield      #3                  // Field any:Ljava/lang/String;
 *         14: aload_0
 *         15: aload_2
 *         16: putfield      #3                  // Field any:Ljava/lang/String;
 *         19: return
 *       LineNumberTable:
 *         line 191: 0
 *         line 190: 9
 *         line 191: 14
 *       LocalVariableTable:
 *         Start  Length  Slot  Name   Signature
 *             0      20     0  this   Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess$InnerClass;
 *             0      20     1 this$0   Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;
 *             0      20     2   any   Ljava/lang/String;
 *
 *   void println() throws java.lang.Exception;
 *     descriptor: ()V
 *     flags:
 *     Code:
 *       stack=2, locals=2, args_size=1
 *          0: aload_0
 *          1: getfield      #1                  // Field this$0:Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;
 *          4: invokestatic  #4                  // Method panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess.access$000:(Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;)I
 *          7: aload_0
 *          8: getfield      #1                  // Field this$0:Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;
 *         11: invokestatic  #5                  // Method panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess.access$100:(Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess;)I
 *         14: iadd
 *         15: istore_1
 *         16: return
 *       LineNumberTable:
 *         line 193: 0
 *         line 194: 16
 *       LocalVariableTable:
 *         Start  Length  Slot  Name   Signature
 *             0      17     0  this   Lpanda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess$InnerClass;
 *            16       1     1     a   I
 *     Exceptions:
 *       throws java.lang.Exception
 * }
 * SourceFile: "TestSyntheticAccess.java"
 * InnerClasses:
 *      #18= #6 of #32; //InnerClass=class panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess$InnerClass of class panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess
 *
 * SourceFile: "TestSyntheticAccess.java"
 * InnerClasses:
 *      #15= #5 of #26; //InnerClass=class panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess$InnerClass of class panda/natalia/gothread/suspend/instrument/codesample/TestSyntheticAccess
 *  可以看到, InnerClass 有一个私有变量之外外部类实例, 在自己的<init> 函数里实现
 */
public class TestSyntheticAccess {
    private int inner = 0;
    private int innerMethod() throws Exception {return 1;}

    class InnerClass {
        private String any = null;
        public InnerClass(String any){this.any = any;}
        void println() throws Exception {
            int a = TestSyntheticAccess.this.inner + TestSyntheticAccess.this.innerMethod();
        }
    }

}
